<?php

/*

    MMetaverse - Open Metaverse Access Library

    Copyright (c) 2009 Mary Jane Soft - Marlon J. Manrique

    http://www.maryjanesoft.com
    http://www.marlonj.com

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General
    Public License along with this library; if not, write to the
    Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    Boston, MA  02111-1307  USA

    $Id$

*/

/**
 * @package mjs.mmetaverse.manager
 */

require_once 'MRegion.class.php';
require_once 'MUser.class.php';

/**
 * Database access
 */
class MDataBase {
    /**
     * The metaverse access library
     *
     * @var MMetaverse
     */
    protected $metaverse;

    /**
     * Database access object
     *
     * @var PDO
     */
    protected $db;

    /**
     * Current open databases
     *
     * @var PDO
     */
    private $databases = array();

    /**
     * Create the database access for the metaverse object specified
     *
     * @param MMetaverse $metaverse current metaverse
     */
    public function MDataBase(MMetaverse $metaverse) {
        $this->metaverse = $metaverse;
    }

    /**
     * Check if the database is sqlite
     *
     * @return boolean true if the database engine is sqlite, false otherwise
     */
    private function isSQLite() {
        // Get the database engine name
        $dbEngine = $this->metaverse->getConfig()->getDatabaseEngine();
        // Check if the name is sqlite
        return $dbEngine == 'sqlite';
    }

    /**
     * Throws a database exception with the error info send by the database
     * engine
     */
    private function throwException() {
        // Throw a exception with the error info send by the database engine
        throw new Exception(print_r($this->db->errorInfo(),true));
    }

    /**
     * Try to execute the statement, if not possible throw an exception
     *
     * @param PDOStatement $stmt The statement to execute
     */
    protected function execute($stmt) {
        // Try to execute the statement
        // If the statement can be execute throw an exception
        if(!$stmt->execute())
        {
            $this->throwException();
        }
    }

    /**
     * Fetch the result from the statement, if not possible throw an exception
     *
     * @param PDOStatement $stmt The statement to execute
     * @return array Array with the result of the query
     */
    protected function fetch($stmt) {
        // Fetch the result
        $result = $stmt->fetch();

        // If not result available throw an exception
        if(!$result)
        {
            $this->throwException();
        }

        // Return the result
        return $result;
    }

    /**
     * Prepare the statement, if not possible throw an exception
     *
     * @param PDO $db Database 
     * @param string $sql SQL query to prepare
     * @return PDOStatement The statement prepared
     */
    protected function prepare($db, $sql) {
        // Try to prepare the statement
        $stmt = $db->prepare($sql);

        // If not possible throw an exception
        if(!$stmt)
        {
            $this->throwException();
        }

        // Return the statement
        return $stmt;
    }

    /**
     * Return the assets database
     *
     * @param string $databaseType The database type: assets or users
     * @return MDatabase the database to the resource specified 
     */
    protected function getDatabase($databaseType) {
        // If not sqlite return main database
        if(!$this->isSQLite())
            return $this->db;

        // Open the connection
        if(!isset($this->databases[$databaseType])) {
            // Get the datasource, open the connection and store it
            $dsn = $this->getDataSource($databaseType);

            // Try to open the database
            try {
                $this->databases[$databaseType] = new PDO($dsn);
            } catch (Exception $e) {
                throw new Exception('Unable to Open Database');
            }
        }

        // Return the database 
        return $this->databases[$databaseType];
    }

    /**
     * Return the database source according the database type 
     *
     * @param string $databaseType The database type: assets or users
     * @return string The database source name 
     */
    private function getDataSource($databaseType) {
        // If the engine is sqlite create dsn with the path of the simulator
        if($this->isSQLite())
        {
            // Get opensim path
            $dir = $this->metaverse->getConfig()->getOpenSimPath();

            // Check database type
            switch($databaseType)
            {
                case 'asset' : $databaseFilename = 'AssetStorage.db'; break;
                case 'user' : $databaseFilename = 'userprofiles.db'; break;
                case 'region' : $databaseFilename = 'OpenSim.db'; break;
                case 'inventory' : $databaseFilename = 'inventoryStore.db'; break;
            }
            
            // Append database file to the datasource
            $dsn = 'sqlite:' . $dir . '/' . $databaseFilename;
        }

        // Return the datasource name
        return $dsn;
    }
}
?>